//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>
#include "ddktstthread.h"
#include "ddktstserver.h"

extern int g_nRet;
extern int g_nErr;
int g_nSchedule1, g_nSchedule2;

int dzyieldthread12(void *parg)
{
    while (1) {
        g_nSchedule2++;
        DzDelay(100);
        DzYield();
    }

    return 0;
}
int dzyieldthread11(void *parg)
{
    while (1) {
        g_nSchedule1++;
        DzDelay(100);
    }

    return 0;
}
ECode ThdTstDzYield1()
{
    ECode ec = NOERROR;
    const int nThreadNum = 2;
    IThread *iSubThread[nThreadNum];
    g_nSchedule1 = 0;
    g_nSchedule2 = 0;
    kprintf("ThdTstDzYield2\n");
    for (int i = 0; i < nThreadNum; i++) {
        ec = DzCreateKernelThread(dzyieldthread11, NULL, 0, ThreadPriorityRank_Normal, &iSubThread[i]);
        if (FAILED(ec)) {
            kprintf("%d, 0x%08x\n", __LINE__, ec);
            break;
        }
    }
    DzSleep(DzMillisecondsToTicks(3000), NULL);
    for (int i = 0; i < nThreadNum; i++) {
        iSubThread[i]->Abort();
        iSubThread[i] = NULL;
    }
    kprintf("g_nSchedule1: %d\n", g_nSchedule1);

    for (int i = 0; i < nThreadNum; i++) {
        ec = DzCreateKernelThread(dzyieldthread12, NULL, 0, ThreadPriorityRank_Normal, &iSubThread[i]);
        if (FAILED(ec)) {
            kprintf("%d, 0x%08x\n", __LINE__, ec);
            break;
        }
    }
    DzSleep(DzMillisecondsToTicks(3000), NULL);
    for (int i = 0; i < nThreadNum; i++) {
        iSubThread[i]->Abort();
        iSubThread[i] = NULL;
    }
    kprintf("g_nSchedule2: %d\n", g_nSchedule2);

    if (g_nSchedule1 > g_nSchedule2)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzyieldthread22(void *parg)
{
    while (1) {
        g_nSchedule2++;
        DzYield();
    }

    return 0;
}
int dzyieldthread21(void *parg)
{
    while (1) {
        g_nSchedule1++;
        DzYield();
    }

    return 0;
}
ECode ThdTstDzYield2()
{
    ECode ec = NOERROR;
    IThread *iSubThread[2];
    int nSchedule = 0;
    g_nSchedule1 = 0;
    g_nSchedule2 = 0;

    ec = DzCreateKernelThread(dzyieldthread21, NULL, 0, ThreadPriorityRank_Normal, &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = iSubThread[0]->SetPriority(ThreadPriority_BelowNormal);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    DzSleep(DzMillisecondsToTicks(500), NULL);
    nSchedule = g_nSchedule1;

    ec = DzCreateKernelThread(dzyieldthread22, NULL, 0, ThreadPriorityRank_Normal, &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    DzSleep(DzMillisecondsToTicks(1000), NULL);
    for (int i = 0; i < 2; i++) {
        iSubThread[i]->Abort();
        iSubThread[i] = NULL;
    }

    if (nSchedule == g_nSchedule1)
        return NOERROR;
    else {
        kprintf("nSchedule: %d, g_nSchedule1: %d\n", nSchedule, g_nSchedule1);
        return E_DDKTST_ERROR1;
    }
}

//------------------------------------------------------------------------------
int dzyieldthread33(void *parg)
{
    if (2 == g_nRet) g_nRet = 3;
    return 0;
}
int dzyieldthread32(void *parg)
{
    if (1 == g_nRet) g_nRet = 2;
    return 0;
}
int dzyieldthread31(void *parg)
{
    IThread *iSubThread1 = NULL;
    IThread *iSubThread2 = NULL;
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzyieldthread32, NULL, 1, ThreadPriorityRank_SoftRealTime, &iSubThread1);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = DzCreateKernelThread(dzyieldthread33, NULL, 1, ThreadPriorityRank_SoftRealTime, &iSubThread2);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    g_nRet = 1;
    DzYield();

    if (3 == g_nRet) g_nRet = 4;
    iSubThread1->Join(INFINITE, NULL);
    iSubThread1->Release();
    iSubThread2->Join(INFINITE, NULL);
    iSubThread2->Release();

    return 0;
}
ECode ThdTstDzYield3()
{
    IThread *iSubThread = NULL;
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzyieldthread31, NULL, 1, ThreadPriorityRank_SoftRealTime, &iSubThread);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }

    iSubThread->Join(INFINITE, NULL);
    iSubThread->Release();

    kprintf("g_nRet: %d\n", g_nRet);
    if (4 == g_nRet)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzyieldthread42(void *parg)
{
    if (1 == g_nRet) g_nRet = 2;
    return 0;
}
int dzyieldthread41(void *parg)
{
    IThread *iSubThread = NULL;
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzyieldthread42, NULL, 1, ThreadPriorityRank_SoftRealTime, &iSubThread);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = iSubThread->SetPriority(ThreadPriority_BelowNormal);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }

    g_nRet = 1;
    DzYield();
    if (1 == g_nRet) g_nRet = 3;
    iSubThread->Join(INFINITE, NULL);
    iSubThread->Release();

    return 0;
}
ECode ThdTstDzYield4()
{
    IThread *iSubThread = NULL;
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzyieldthread41, NULL, 1, ThreadPriorityRank_SoftRealTime, &iSubThread);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }

    iSubThread->Join(INFINITE, NULL);
    iSubThread->Release();

    kprintf("g_nRet: %d\n", g_nRet);
    if (3 == g_nRet)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzyieldthread5(void *parg)
{
    int nRunTimes = (int)parg;
    for (int i = 0; i < nRunTimes; i++) {
        DzYield();
    }

    return 0;
}

ECode ThdTstDzYield5()
{
    ECode ec = NOERROR;
    IThread *iSubThread = NULL;
    int nRunTimes = 10000;

    ec = DzCreateKernelThread(dzyieldthread5,
                              (void *)nRunTimes,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }

    for (int i = 0; i < nRunTimes; i++) {
        DzYield();
    }

    iSubThread->Join(INFINITE, NULL);
    iSubThread->Release();

    return 0;
}

//------------------------------------------------------------------------------
int dzsleepthread12(void *parg)
{
    IThread *iThread = (IThread *)parg;
    ThreadState nState;

    do {
        iThread->GetState(&nState);
        DzSleep(10, NULL);
    } while (ThreadState_Sleeping != nState);

    iThread->Interrupt();

    iThread->GetState(&nState);
    if (ThreadState_Running != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 1;
    }
    return 0;
}
int dzsleepthread11(void *parg)
{
    DzSleep();
    DzDelay(2 * 1000 * 1000);
    return 0;
}
ECode ThdTstDzSleep1()
{
    IThread *iSubThread[2];
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzsleepthread11,
                              NULL,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = DzCreateKernelThread(dzsleepthread12,
                              iSubThread[0],
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        iSubThread[0]->Release();
        return ec;
    }

    for (int i = 0; i < 2; i++) {
        iSubThread[i]->Join(INFINITE, NULL);
        iSubThread[i]->Release();
    }

    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzsleepthread22(void *parg)
{
    IThread *iThread = (IThread *)parg;
    ThreadState nState;

    iThread->GetState(&nState);
    if (ThreadState_Running != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 1;
    }

    iThread->Interrupt();
    DzDelay(2 * 1000 * 1000);
    iThread->GetState(&nState);
    if (ThreadState_Finished != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 2;
    }
    return 0;
}
int dzsleepthread21(void *parg)
{
    DzDelay(1 * 1000 * 1000);
    DzSleep();
    return 0;
}
ECode ThdTstDzSleep2()
{
    IThread *iSubThread[2];
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzsleepthread21,
                              NULL,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = DzCreateKernelThread(dzsleepthread22,
                              iSubThread[0],
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        iSubThread[0]->Release();
        return ec;
    }

    iSubThread[1]->Join(INFINITE, NULL);
    iSubThread[1]->Release();
    iSubThread[0]->Join(INFINITE, NULL);
    iSubThread[0]->Release();

    kprintf("g_nErr: %d\n", g_nErr);
    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzsleepthread32(void *parg)
{
    IThread *iThread = (IThread *)parg;
    ThreadState nState;

    do {
        iThread->GetState(&nState);
        DzSleep(10, NULL);
    } while (ThreadState_Sleeping != nState);

    iThread->Interrupt();

    iThread->GetState(&nState);
    if (ThreadState_Running != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 1;
    }

    return 0;
}
int dzsleepthread31(void *parg)
{
    DzSleep();
    return 0;
}
ECode ThdTstDzSleep3()
{
    IThread *iSubThread[2];
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzsleepthread31,
                              NULL,
                              1,
                              ThreadPriorityRank_SoftRealTime,
                              &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = DzCreateKernelThread(dzsleepthread32,
                              iSubThread[0],
                              1,
                              ThreadPriorityRank_SoftRealTime,
                              &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        iSubThread[0]->Release();
        return ec;
    }

    for (int i = 0; i < 2; i++) {
        iSubThread[i]->Join(INFINITE, NULL);
        iSubThread[i]->Release();
    }

    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
ECode ThdTstDzSleep4()
{
    WaitResult wr;

    DzSleep(DzMillisecondsToTicks(10), &wr);
    if (WaitResult_TimedOut != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 1;
    }

    DzSleep(0, &wr);
    if (WaitResult_TimedOut != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 2;
    }

    DzSleep(DzMillisecondsToTicks(1000), &wr);
    if (WaitResult_TimedOut != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 3;
    }

    DzSleep(DzMillisecondsToTicks(2000), &wr);
    if (WaitResult_TimedOut != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 4;
    }

    kprintf("g_nErr: %d\n", g_nErr);
    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzsleepthread51(void *parg)
{
    WaitResult wr;

    DzSleep(DzMillisecondsToTicks(10000), &wr);
    if (WaitResult_Interrupted != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 1;
    }

    return 0;
}
ECode ThdTstDzSleep5()
{
    IThread *iSubThread;
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzsleepthread51,
                              NULL,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    DzDelay(1000 * 1000);

    iSubThread->Interrupt();
    iSubThread->Join(INFINITE, NULL);
    iSubThread->Release();

    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzsleepthread62(void *parg)
{
    IThread *iThread = (IThread *)parg;
    ThreadState nState;

    iThread->GetState(&nState);
    if (ThreadState_Running != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 1;
    }

    iThread->Interrupt();
    DzDelay(2 * 1000 * 1000);
    iThread->GetState(&nState);
    if (ThreadState_Finished != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 2;
    }
    return 0;
}
int dzsleepthread61(void *parg)
{
    WaitResult wr;
    DzDelay(1 * 1000 * 1000);
    DzSleep(DzMillisecondsToTicks(5000), &wr);
    if (WaitResult_Interrupted != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 3;
    }

    return 0;
}
ECode ThdTstDzSleep6()
{
    IThread *iSubThread[2];
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzsleepthread61,
                              NULL,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = DzCreateKernelThread(dzsleepthread62,
                              iSubThread[0],
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        iSubThread[0]->Release();
        return ec;
    }

    iSubThread[1]->Join(INFINITE, NULL);
    iSubThread[1]->Release();
    iSubThread[0]->Join(INFINITE, NULL);
    iSubThread[0]->Release();

    kprintf("g_nErr: %d\n", g_nErr);
    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzsleepthread72(void * parg)
{
    SystemTime etSystemTime1;
    SystemTime etSystemTime2;
    ulong_t utMicroSeconds1 = (ulong_t)parg;
    ulong_t utMicroSeconds2 = 0;

    DzGetSystemTime(&etSystemTime1);
    DzSleep(DzMillisecondsToTicks(500), NULL);
    DzGetSystemTime(&etSystemTime2);

    utMicroSeconds2 = etSystemTime2.seconds * 1000000
                      + etSystemTime2.microseconds
                      - etSystemTime1.seconds * 1000000
                      - etSystemTime1.microseconds;

    if (utMicroSeconds1 > utMicroSeconds2)
        utMicroSeconds1 = (utMicroSeconds1 - utMicroSeconds2) / 1000;
    else
        utMicroSeconds1 = (utMicroSeconds2 - utMicroSeconds1) / 1000;

    kprintf("SubThread: %d\n", utMicroSeconds1);

    return 0;
}
ECode ThdTstDzSleep7()
{
    SystemTime etSystemTime1;
    SystemTime etSystemTime2;
    ulong_t utMicroSeconds1 = 0;
    ulong_t utMicroSeconds2 = 0;
    IThread *iSubThread = NULL;
    ECode ec = NOERROR;

    DzGetSystemTime(&etSystemTime1);
    DzGetSystemTime(&etSystemTime2);
    utMicroSeconds1 = etSystemTime2.seconds * 1000000
                      + etSystemTime2.microseconds
                      - etSystemTime1.seconds * 1000000
                      - etSystemTime1.microseconds;

    ec = DzCreateKernelThread(dzsleepthread72,
                              (void *)utMicroSeconds1,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }

    DzGetSystemTime(&etSystemTime1);
    DzSleep(DzMillisecondsToTicks(1000), NULL);
    DzGetSystemTime(&etSystemTime2);

    utMicroSeconds2 = etSystemTime2.seconds * 1000000
                      + etSystemTime2.microseconds
                      - etSystemTime1.seconds * 1000000
                      - etSystemTime1.microseconds;

    if (utMicroSeconds1 > utMicroSeconds2)
        utMicroSeconds1 = (utMicroSeconds1 - utMicroSeconds2) / 1000;
    else
        utMicroSeconds1 = (utMicroSeconds2 - utMicroSeconds1) / 1000;

    kprintf("MainThread: %d\n", utMicroSeconds1);
    iSubThread->Join(INFINITE, NULL);
    iSubThread->Release();

    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzsleepthread82(void *parg)
{
    IThread *iThread = (IThread *)parg;
    ThreadState nState;

    iThread->Interrupt();
    iThread->Interrupt();
    DzDelay(2 * 1000 * 1000);
    iThread->GetState(&nState);
    if (ThreadState_Finished != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 1;
    }

    return 0;
}
int dzsleepthread81(void *parg)
{
    WaitResult wr;
    DzDelay(1 * 1000 * 1000);
    DzSleep(DzMillisecondsToTicks(60000), &wr);
    if (WaitResult_Interrupted != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 2;
    }
    DzSleep(DzMillisecondsToTicks(500), &wr);
    if (WaitResult_TimedOut != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 3;
    }

    return 0;
}
ECode ThdTstDzSleep8()
{
    IThread *iSubThread[2];
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzsleepthread81,
                              NULL,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = DzCreateKernelThread(dzsleepthread82,
                              iSubThread[0],
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        iSubThread[0]->Release();
        return ec;
    }

    iSubThread[1]->Join(INFINITE, NULL);
    iSubThread[1]->Release();
    iSubThread[0]->Join(INFINITE, NULL);
    iSubThread[0]->Release();

    kprintf("g_nErr: %d\n", g_nErr);
    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzsleepthread92(void *parg)
{
    ECode ec = NOERROR;
    IThread *iThread = (IThread *)parg;
    int i = 0;

    while (1) {
        ec = iThread->Interrupt();
        if (FAILED(ec)) {
            kprintf("%d, 0x%08x, %d\n", __LINE__, ec, i);
            g_nErr = 1;
            break;
        }
        i++;
    }

    return 0;
}
int dzsleepthread91(void *parg)
{
    WaitResult wr;
    int i = 0;

    while (1) {
        DzSleep(DzMillisecondsToTicks(i), &wr);
        if ((WaitResult_Interrupted != wr) && (WaitResult_TimedOut != wr)) {
            kprintf("%d, %d, %d\n", __LINE__, wr, i);
            g_nErr = 2;
            break;
        }
        i++;
    }

    return 0;
}
ECode ThdTstDzSleep9()
{
    IThread *iSubThread[2];
    ECode ec = NOERROR;

    ec = DzCreateKernelThread(dzsleepthread91,
                              NULL,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    ec = DzCreateKernelThread(dzsleepthread92,
                              iSubThread[0],
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        iSubThread[0]->Release();
        return ec;
    }

    DzSleep(DzMillisecondsToTicks(10000), NULL);
    iSubThread[1]->Abort();
    iSubThread[1]->Release();
    iSubThread[0]->Abort();
    iSubThread[0]->Release();

    kprintf("g_nErr: %d\n", g_nErr);
    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzdelaythread12(void * parg)
{
    IThread *iSubThread = (IThread *)parg;

    ThreadState nState;
    iSubThread->GetState(&nState);
    if (ThreadState_Running != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 1;
    }

    return 0;
}
int dzdelaythread11(void * parg)
{
    DzDelay(2 * 1000 * 1000);
    return 0;
}
ECode ThdTstDzDelay1()
{
    IThread *iSubThread[2];
    ECode ec = NOERROR;
    g_nRet = 0;

    ec = DzCreateKernelThread(dzdelaythread11,
                              NULL,
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    DzSleep(DzMillisecondsToTicks(100), NULL);

    ec = DzCreateKernelThread(dzdelaythread12,
                              iSubThread[0],
                              0,
                              ThreadPriorityRank_Normal,
                              &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        iSubThread[0]->Release();
        return ec;
    }

    iSubThread[0]->Join(INFINITE, NULL);
    iSubThread[0]->Release();
    iSubThread[1]->Join(INFINITE, NULL);
    iSubThread[1]->Release();

    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzdelaythread22(void * parg)
{
    IThread *iSubThread = (IThread *)parg;

    ThreadState nState;
    iSubThread->GetState(&nState);
    if (ThreadState_Finished != nState) {
        kprintf("%d, %d\n", __LINE__, nState);
        g_nErr = 1;
    }

    return 0;
}
int dzdelaythread21(void * parg)
{
    DzDelay(2 * 1000 * 1000);
    return 0;
}
ECode ThdTstDzDelay2()
{
    IThread *iSubThread[2];
    ECode ec = NOERROR;
    g_nRet = 0;

    ec = DzCreateKernelThread(dzdelaythread21,
                              NULL,
                              1,
                              ThreadPriorityRank_SoftRealTime,
                              &iSubThread[0]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        return ec;
    }
    DzSleep(DzMillisecondsToTicks(100), NULL);

    ec = DzCreateKernelThread(dzdelaythread22,
                              iSubThread[0],
                              1,
                              ThreadPriorityRank_SoftRealTime,
                              &iSubThread[1]);
    if (FAILED(ec)) {
        kprintf("%d, 0x%08x\n", __LINE__, ec);
        iSubThread[0]->Release();
        return ec;
    }

    iSubThread[0]->Join(INFINITE, NULL);
    iSubThread[0]->Release();
    iSubThread[1]->Join(INFINITE, NULL);
    iSubThread[1]->Release();

    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}

//------------------------------------------------------------------------------
int dzdelaythread31(void * parg)
{
    WaitResult wr;

    DzSleep(DzMillisecondsToTicks(0), &wr);
    if (WaitResult_TimedOut != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 1;
    }
    DzSleep(DzMillisecondsToTicks(500), &wr);
    if (WaitResult_TimedOut != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 2;
    }
    DzSleep(DzMillisecondsToTicks(1000), &wr);
    if (WaitResult_TimedOut != wr) {
        kprintf("%d, %d\n", __LINE__, wr);
        g_nErr = 3;
    }

    DzYield();

    DzDelay(0);

    DzDelay(500 * 1000);

    DzDelay(1000 * 1000);

    return 0;
}
ECode ThdTstDzDelay3()
{
    const int nThreadNum = 20;
    IThread *iSubThread[nThreadNum];
    ECode ec = NOERROR;

    for (int i = 0; i < nThreadNum; i++) {
        iSubThread[i] = NULL;
    }

    for (int i = 0; i < nThreadNum; i++) {
        ec = DzCreateKernelThread(dzdelaythread31,
                                  NULL,
                                  0,
                                  ThreadPriorityRank_Normal,
                                  &iSubThread[i]);
        if (FAILED(ec)) {
            kprintf("%d, 0x%08x\n", __LINE__, ec);
            goto exit;
        }
    }

exit:
    for (int i = 0; i < nThreadNum; i++) {
        if (iSubThread[i]) {
            iSubThread[i]->Join(INFINITE, NULL);
            iSubThread[i]->Release();
        }
    }

    kprintf("g_nErr: %d\n", g_nErr);
    if (!g_nErr)
        return NOERROR;
    else
        return E_DDKTST_ERROR1;
}
